import { SearchOutlined, ApiOutlined, ReloadOutlined } from '@ant-design/icons'
import { getLogger, formatTime } from '@gnlab/utils'
import { message, Button } from 'antd'
import { Empty, Loading } from '@/desktop/components'
import { useStreams } from '@/lib/utils'
import services from '@/services'
import type { ExternalContact } from '@/services/contact-types'
import { ContactType } from '@/services/contacts'
import type { OfficialData } from '@/services/features/new-rank'
import { Articles } from './articles'
import { Search } from './search'
import './index.module.less'

const logger = getLogger('ui/new-rank')

function parseGhid(contactDescribe: string, idPattern: string) {
  try {
    // 用户正则匹配出的结果可能带有额外内容（空格、前缀后缀字符），需二次处理
    const matched = new RegExp(idPattern).exec(contactDescribe)?.[0] ?? ''
    const trimmed = matched
      .trim() // 排除匹配结果首尾的空格
      .split(' ')[0]! // 若结果中间有空格，只取空格前的内容
    const cleaned = /gh_[a-zA-Z0-9]+/.exec(trimmed)?.[0] ?? '' // 移除前后缀字符
    return cleaned
  } catch (e) {
    logger.error('解析 ghid 出错', e)
    return ''
  }
}

export default function NewRank() {
  const [contact, config] = useStreams(
    services.contacts.current.contact,
    services.features.newRank.config,
  )
  if (!contact || contact.type !== ContactType.external || !config) return null
  return <Content contact={contact} idPattern={config.idPattern} />
}

function Content({ contact, idPattern }: { contact: ExternalContact; idPattern: string }) {
  const contactId = contact.id
  const contactDescribe = contact.describe

  const [notice, setNotice] = useState('')

  // undefined: 加载中  null: 无公众号数据  data
  const [official, setOfficial] = useState<OfficialData | null | undefined>(undefined)
  useEffect(() => {
    void services.features.newRank.getData(contactId).then(res => {
      if (res.success) {
        setOfficial(res.data)
      } else {
        setNotice('获取公众号数据失败：' + res.error)
        setOfficial(null)
      }
    })
  }, [contactId])

  const [fetching, setFetching] = useState(false)
  async function fetchFromNewRank() {
    if (fetching) return

    setNotice('')
    const ghid = official?.ghid ?? parseGhid(contactDescribe, idPattern)
    if (!ghid) return void setNotice('公众号ID解析失败，请检查客户描述里是否有符合规则的ID。')

    setFetching(true)
    const res = await services.features.newRank.fetchDataFromNewRank(contactId, ghid)
    setFetching(false)
    if (res.success) {
      void message.success(official ? '数据刷新成功' : '公众号数据获取成功')
      setOfficial(res.data)
    } else {
      void message.warning('新榜接口拉取公众号失败：' + res.error)
    }
  }

  const [showArticles, setShowArticles] = useState(false)
  const [searching, setSearching] = useState(false)
  function finishSearch(data?: OfficialData) {
    if (data) setOfficial(data)
    setSearching(false)
  }

  if (official === undefined) return <Loading />

  let content: JSX.Element
  if (official) {
    const empty = <span styleName="empty">暂无</span>
    content = <>
      <section styleName="base-info">
        <div styleName="row">
          <label>公众号名称</label>
          <div>{official.name}</div>
        </div>
        <div styleName="row">
          <label>公众号类型</label>
          <div>{official.type || empty}</div>
        </div>
      </section>
      <section styleName="count">
        <h4>近一个月发布文章数据</h4>
        <div styleName="row">
          <label>平均阅读量</label>
          <div>{Math.round(official.readNum)}</div>
        </div>
        <div styleName="row">
          <label>平均在看量</label>
          <div>{Math.round(official.likeNum)}</div>
        </div>
        <div styleName="row">
          <label>平均点赞量</label>
          <div>{Math.round(official.preLikeNum)}</div>
        </div>
        <div styleName="row">
          <label>平均评论量</label>
          <div>{Math.round(official.commentNum)}</div>
        </div>
        <div styleName="row">
          <a onClick={() => setShowArticles(true)}>查看详细数据</a>
        </div>
        <div styleName="row updated">数据获取时间：{formatTime(official.updated)}</div>
      </section>
    </>
  } else {
    content = <Empty styleName="official-empty" description="尚未取得公众号数据" />
  }

  return <div styleName="wrap">
    <header>
      <Button type="link" icon={<SearchOutlined />} onClick={() => setSearching(true)}>
        查找公众号
      </Button>
      {!official ? (
        <Button type="link" icon={<ApiOutlined />} onClick={fetchFromNewRank}>
          获取数据
        </Button>
      ) : (
        <Button type="link" icon={<ReloadOutlined />} onClick={fetchFromNewRank}>
          刷新数据
        </Button>
      )}
    </header>

    {notice ? <div styleName="notice">{notice}</div> : null}

    <main>{content}</main>

    {official ? (
      <footer>
        <span>公众号ID：{official.account}</span>
        <span>公众号原始ID：{official.ghid}</span>
      </footer>
    ) : null}

    <Articles open={showArticles} contactId={contactId} onClose={() => setShowArticles(false)} />
    <Search open={searching} contactId={contactId} onClose={finishSearch} />
  </div>
}
